﻿using System;

namespace ComplexNumbers
{
    class ComplexNumber
    {
        private double real;
        private double imaginary;

        public ComplexNumber(double realPart, double imaginaryPart)
        {
            real = realPart;
            imaginary = imaginaryPart;
        }

        public static ComplexNumber operator +(ComplexNumber cn1, ComplexNumber cn2)
        {
            double newRealPart = cn1.real + cn2.real;
            double newImaginaryPart = cn1.imaginary + cn2.imaginary;
            ComplexNumber result = new ComplexNumber(newRealPart, newImaginaryPart);
            return result;
        }

        public static ComplexNumber operator -(ComplexNumber cn1, ComplexNumber cn2)
        {
            double newRealPart = cn1.real - cn2.real;
            double newImaginaryPart = cn1.imaginary - cn2.imaginary;
            ComplexNumber result = new ComplexNumber(newRealPart, newImaginaryPart);
            return result;
        }

        public static ComplexNumber operator *(ComplexNumber cn1, ComplexNumber cn2)
        {
            double newRealPart = cn1.real * cn2.real - cn1.imaginary * cn2.imaginary;
            double newImaginaryPart = cn1.imaginary * cn2.real + cn1.real * cn2.imaginary;
            ComplexNumber result = new ComplexNumber(newRealPart, newImaginaryPart);
            return result;
        }

        public static ComplexNumber operator /(ComplexNumber cn1, ComplexNumber cn2)
        {
            if (cn2.real == 0 && cn2.imaginary == 0)
            {
                throw new ArgumentOutOfRangeException("Can not divide by zero!");
            }

            double denominator = cn2.real * cn2.real + cn2.imaginary * cn2.imaginary;

            double newRealPart = (cn1.real * cn2.real + cn1.imaginary * cn2.imaginary) / denominator;
            double newImaginaryPart = (cn1.imaginary * cn2.real - cn1.real * cn2.imaginary) / denominator;
            ComplexNumber result = new ComplexNumber(newRealPart, newImaginaryPart);
            return result;
        }

        public static explicit operator double(ComplexNumber number)
        {
            double result = number.real;
            return result;
        }

        public static implicit operator ComplexNumber(double number)
        {
            ComplexNumber result = new ComplexNumber(number, 0);
            return result;
        }

        public override string ToString()
        {
            string toString = string.Format("{0} + {1}i", real, imaginary);
            return toString;
        }

        public double this[int index]
        {
            get
            {
                if (index < 0 || index > 1)
                {
                    throw new IndexOutOfRangeException("Index should be 0 or 1.");
                }
                if (index == 0)
                    return real;
                else return imaginary;
            }
            set
            {
                if (index < 0 || index > 1)
                {
                    throw new IndexOutOfRangeException("Index should be 0 or 1.");
                }
                if (index == 0)
                    real = value;
                else imaginary = value;

            }
        }
    }
}
